#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <cstdlib>

#include <string>
using namespace std;
// father --> read and child --> write

// 0 -- read  1--write 下标的作用就是这样的
int main()
{
    cout << "hello world" << endl;
    int fds[2] = {0}; // fds为输出型参数

    int n = pipe(fds);

    if (n == 0)
    {
        std::cout << "fds[0] = " << fds[0] << std::endl;

        std::cout << "fds[1] = " << fds[1] << std::endl;
    }
    else
    {
        std::cout << "pipe error" << std::endl;

        return 1;
    }

    // 2. 创建子进程
    pid_t id = fork();
    if (id < 0)
    {
        std::cerr << "fork error" << std::endl;
        return 2;
    }
    else if (id == 0)
    {
        // 子进程
        // 3. 关闭不需要的 fd
        // 关闭读方式
        ::close(fds[0]); // :: 在这立就只是一个标志，表示这个函数就是全局的库函数！

        //
        int cnt = 0;

        int total = 0;
        while (1)
        {
            std::string message = "h";
            // message += std::to_string(getpid());
            // message += " , ";
            // message += std::to_string(++cnt);

            // fds[1] : 现在需要向父进程发送消息
            // 本质上 linux 就是需要文件这样的方式来实现通信

            total += ::write(fds[1], message.c_str(), message.size());

            std::cout << " total :" << total << std::endl;
            // sleep(1);
        }

        exit(0);
    }
    else
    {
        // 关闭写方式
        ::close(fds[1]); // 父进程

        char buffer[1024] = {0};
        while(true)
        {
            sleep(10);
            ssize_t n = ::read(fds[0], buffer, sizeof buffer / 2);
            if (n > 0)
            {
                buffer[n] = 0;

                std::cout << "father read from child process:" << buffer << std::endl;
            } 

            else if (n == 0)
            {
                // 如果写段关闭，
                // 读端读完管道内的所有数据，再读取的时候，就会读取返回的0
                // 表示对端关闭
                std::cout << "child process close write end" << std::endl;

                break;
            }
            else break;

            close(fds[0]); // 关闭读端
            break;
            std::cout << std::endl;
        }
        int status = 0;
        pid_t rid = waitpid(id, &status, 0);
        std::cout << "father wait child process success !" 
        << rid << " exit code: " << ((status << 8) & 0xFF )
        << ", exit sig: " << (status & 0x7F) << std::endl;
    }
    return 0;
}

// zdl::正确的地址重定向的语法就是需要将 2 号的下表重定向到 2

// 1.现在我们就知道了， 管道也有上限！